package com.gl.saasservice.sys.service;

import com.alibaba.fastjson.JSON;
import com.gl.common.constant.Constants;
import com.gl.common.util.redis.RedisUtils;
import com.gl.framework.web.response.Result;
import com.gl.saasservice.entity.Permission;
import com.gl.saasservice.entity.RolePermission;
import com.gl.saasservice.entity.UserRole;
import com.gl.saasservice.sys.mapper.LevelRowMapper;
import com.gl.saasservice.sys.mapper.PermissionRowMapper;
import com.gl.saasservice.repository.DepartmentRoleRecordRepository;
import com.gl.saasservice.repository.PermissionRepository;
import com.gl.saasservice.repository.RolePermissionRepository;
import com.gl.saasservice.repository.UserRoleRepository;
import com.gl.saasservice.sys.utils.CheckUtil;
import com.gl.saasservice.sys.vo.LevelVO;
import com.gl.saasservice.sys.vo.PermissionVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 权限管理
 */
@Service
public class PermissionService {
    private static final Logger LOG = LoggerFactory.getLogger(PermissionService.class);

    @Autowired
    private PermissionRepository permissionRepository;
    @Autowired
    private RolePermissionRepository rolePermissionRepository;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private UserRoleRepository userRoleRepository;
    @Autowired
    private DepartmentRoleRecordRepository departmentRoleRecordRepository;


    public Result save(String accessToken, PermissionVO permissionVO) {
        LOG.info("PermissionService save accessToken={},permissionVO={}", accessToken, JSON.toJSONString(permissionVO));

        CheckUtil checkUtil = new CheckUtil();
        checkUtil.checkValues(permissionVO);
        if (checkUtil.isNull()){
            return Result.fail(checkUtil.getMessage());
        }

        Optional<Permission> byId = permissionRepository.findById(permissionVO.getParentId());
        if (!byId.isPresent() && permissionVO.getParentId() != 0){
            return Result.fail("父权限信息不存在！");
        }

        Permission permission = new Permission();
        BeanUtils.copyProperties(permissionVO,permission);
        permissionRepository.save(permission);

        //更新权限,删除权限redis
        if(permissionVO.getId() != null) {
        	
        	List<RolePermission> rolePermissinList = rolePermissionRepository.findByPermissionId(permissionVO.getId());
        	
        	if(rolePermissinList == null || rolePermissinList.isEmpty()) {
        		 return Result.success(null);
        	}
        	List<Long> ids = new ArrayList<>();
        	rolePermissinList.forEach(rp->ids.add(rp.getRoleId()));
        	
        	List<UserRole> userRoleList =  userRoleRepository.findByRoleIdIn(ids);
        	
        	if(userRoleList == null || userRoleList.isEmpty()) {
        		return Result.success(null);
        	}
        	
        	//删除用户权限缓存
            for(UserRole userRole : userRoleList) {
                redisUtils.del(Constants.SAAS_USER_PERMISSION+ ":" +userRole.getUserId());
            }
            redisUtils.del(Constants.SAAS_PERMISSION);
        }
        
        
        return Result.success(null);
        }

    public Result delete (String accessToken, Long id){
        LOG.info("PermissionService delete accessToken={},id={}", accessToken, id);

        Optional<Permission> optional = permissionRepository.findById(id);
        if (!optional.isPresent()) {
            return Result.fail("当前权限数据不存在！");
        }
        Permission permission = optional.get();
        List<Long> permissionsIdList = new ArrayList<>();;
        permissionsIdList.add(permission.getId());

        if (permission.getParentId() == 0){
            List<Permission> permissionChildrenList = permissionRepository.findByParentId(permission.getId());
            if (Objects.nonNull(permissionChildrenList)){
                permissionChildrenList.forEach((permissionChildren)->{
                    permissionsIdList.add(permissionChildren.getId());
                });
            }
        }
        
        List<RolePermission> rolePermissinList = rolePermissionRepository.findByPermissionIdIn(permissionsIdList);
        permissionRepository.deleteByIdIn(permissionsIdList);
        rolePermissionRepository.deleteByPermissionIdIn(permissionsIdList);
        departmentRoleRecordRepository.deleteByPermissionIdIn(permissionsIdList);

    	if(rolePermissinList == null || rolePermissinList.isEmpty()) {
    		 return Result.success(null);
    	}
    	List<Long> ids = new ArrayList<>();
    	rolePermissinList.forEach(rp->ids.add(rp.getRoleId()));
    	
    	List<UserRole> userRoleList =  userRoleRepository.findByRoleIdIn(ids);
    	
    	if(userRoleList == null || userRoleList.isEmpty()) {
    		return Result.success(null);
    	}
    	
    	//删除用户权限缓存
        for(UserRole userRole : userRoleList) {
            redisUtils.del(Constants.SAAS_USER_PERMISSION+ ":" +userRole.getUserId());
        }
        redisUtils.del(Constants.SAAS_PERMISSION);
        
        return Result.success(null);
    }

    public Map<String, Object> pages(String accessToken,Long parentId, String filter) throws Exception {
        LOG.info("PermissionService pages accessToken={},parentId={},filter={}", accessToken, parentId,filter);

        StringBuffer sql = new StringBuffer(
                "select id, parent_id, name, type, url, method, code, icon, sortby, master_show from saas_permission WHERE 1=1");
		if(parentId != null) {
			sql.append(" AND parent_id = ").append(parentId);
		}

        sql.append(" order by sortby");

        List<PermissionVO> list = jdbcTemplate.query(sql.toString(),
                new PermissionRowMapper());
        setLevel(list);

		// 查全部时重排下结果
		if(parentId == null) {
			List<PermissionVO> newList = new LinkedList<PermissionVO>();
			sortList(newList, list);
			list = newList;
		}

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("data", list);
        return map;
    }

    private void sortList(List<PermissionVO> newList, List<PermissionVO> list) {
        for (PermissionVO vo : list) {
            if (vo.getParentId().longValue() == 0) {
                newList.add(vo);
                findChild(vo.getId(), newList, list);
            }
        }
    }

    private void findChild(Long parentId, List<PermissionVO> newList, List<PermissionVO> list) {
        for (PermissionVO vo : list) {
            if (parentId.longValue() == vo.getParentId().longValue()) {
                newList.add(vo);
                findChild(vo.getId(), newList, list);
            }
        }
    }

    private void setLevel(List<PermissionVO> list) throws Exception {

        if (list == null || list.size() <= 0) {
            return;
        }

        List<LevelVO> levelList = findLevel();
        for (PermissionVO pvo : list) {
            for (LevelVO lvo : levelList) {
                if (pvo.getId().longValue() == lvo.getId().longValue()) {
                    pvo.setLevel(lvo.getLevel());
                }
            }
        }
    }
    private List<LevelVO> findLevel() throws Exception {
        String sql = "SELECT id AS ID,parent_id,levels AS 'level',paths AS 'path' \n" +
                "FROM\n" +
                " (SELECT id,parent_id,\n" +
                " @le :=IF(parent_id = 0,0,\n" +
                " IF(\n" +
                " LOCATE( CONCAT( '|', parent_id, ':' ), @pathlevel ) > 0,\n" +
                " SUBSTRING_INDEX( SUBSTRING_INDEX( @pathlevel, CONCAT( '|', parent_id, ':' ),- 1 ), '|', 1 ) + 1,\n" +
                " @le + 1 \n" +
                " ) \n" +
                " ) levels,\n" +
                " @pathlevel := CONCAT( @pathlevel, '|', id, ':', @le, '|' ) pathlevel,\n" +
                " @pathnodes :=IF(parent_id = 0,',0',CONCAT_WS(',',\n" +
                " IF(\n" +
                " LOCATE( CONCAT( '|', parent_id, ':' ), @pathall ) > 0,\n" +
                " SUBSTRING_INDEX( SUBSTRING_INDEX( @pathall, CONCAT( '|', parent_id, ':' ),- 1 ), '|', 1 ),\n" +
                " @pathnodes \n" +
                " ),\n" +
                " parent_id \n" +
                " ) \n" +
                " ) paths,\n" +
                " @pathall := CONCAT( @pathall, '|', id, ':', @pathnodes, '|' ) pathall \n" +
                " FROM saas_permission,( SELECT @le := 0, @pathlevel := '', @pathall := '', @pathnodes := '' ) vv \n" +
                " ORDER BY parent_id,id ) src \n" +
                " ORDER BY id";

        return jdbcTemplate.query(sql, new LevelRowMapper());
    }

/*    public List<PermissionVO> findPermissionByUser(String accessToken,String type) {

        TokenRedisVo tokenRedisVo = redisService.getAccessToken(accessToken);

        String sql = null;
        if ("menu".equalsIgnoreCase(type)) {
            sql = "SELECT DISTINCT p.id, p.parent_id, p.name, p.type, p.url, p.method, p.code, p.icon, p.sortby \n" +
                    " FROM fh_sys_permission p LEFT JOIN fh_sys_role_permission rp ON p.id = rp.PERMISSION_ID \n" +
                    " LEFT JOIN fh_sys_user_role ur ON ur.role_id = rp.role_id \n" +
                    " WHERE ur.user_id = ?";
        }else{
            sql = " select distinct p.id, p.parent_id, p.name, p.type, p.url, p.method, p.code, p.icon, p.sortby "
                    + " from fh_sys_role r " + "left join fh_sys_user_role ur on ur.role_id = r.id "
                    + " left join fh_sys_role_permission rp on rp.role_id = r.id "
                    + " left join fh_sys_permission p on p.id = rp.permission_id "
                    + " where ur.user_id = ? and p.id IS NOT NULL ";
        }

        sql += " order by p.sortby, p.name ";

        List<PermissionVO> list = jdbcTemplate.query(sql, new Object[] { tokenRedisVo.getId() }, new PermissionRowMapper());

        return list;
    }*/

/*    public List<PermissionVO> findPermissionByUserSortby(String accessToken) {

        TokenRedisVo tokenRedisVo = redisService.getAccessToken(accessToken);

        String sql = "SELECT DISTINCT p.id, p.parent_id, p.name, p.type, p.url, p.method, p.code, p.icon, p.sortby \n" +
                " FROM fh_sys_permission p LEFT JOIN fh_sys_role_permission rp ON p.id = rp.PERMISSION_ID \n" +
                " LEFT JOIN fh_sys_user_role ur ON ur.role_id = rp.role_id \n" +
                " WHERE ur.user_id = ?  order by sortby";

        List<PermissionVO> list = jdbcTemplate.query(sql, new Object[] { tokenRedisVo.getId() }, new PermissionRowMapper());
        return list;
    }*/

    public List<PermissionVO> findPermissionAll() {

        String sql = "SELECT p.id, p.parent_id, p.name, p.type, p.url, p.method, p.code, p.icon, p.sortby "
                + "FROM fh_sys_permission p " + "LEFT JOIN fh_sys_role_permission rp ON p.id = rp.PERMISSION_ID "
                + "LEFT JOIN fh_sys_user_role ur ON ur.role_id = rp.role_id "
                + "WHERE p.type = 1 order by p.sortby, p.name";
        List<PermissionVO> list = jdbcTemplate.query(sql, new Object[] {}, new PermissionRowMapper());
        return list;
    }

    public Map<String, Object>  dealwithResult(List<PermissionVO> list)throws Exception{
        List<PermissionVO> menulist=new LinkedList<>();
        List<PermissionVO> buttonlist=new LinkedList<>();
        Short type=1;
        for(PermissionVO permission:list){
            if(permission.getType().equals(type)){
                menulist.add(permission);
            }else{
                buttonlist.add(permission);
            }
        }
        setLevel(menulist);
        setLevel(buttonlist);
        //重排下结果
        List<PermissionVO> newList = new LinkedList<PermissionVO>();
        sortList(newList, menulist);
        menulist = newList;

        Map<String, Object> dataMap   = new HashMap<String, Object>();
        dataMap.put("menulist", menulist);
        dataMap.put("buttonlist", buttonlist);
        return dataMap;
    }
}

